package com.odata.springboot.starter.odata.odata.processor;

import com.odata.springboot.starter.odata.odata.config.OdataCachedData;
import com.odata.springboot.starter.odata.odata.sql.sqlBuild.OdataClassMetaData;
import com.odata.springboot.starter.odata.odata.sql.sqlBuild.OdataSqlInfo;
import com.odata.springboot.starter.odata.odata.sql.sqlBuild.OdataSqlInformation;
import com.odata.springboot.starter.odata.utils.OdataJdbcUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.olingo.commons.api.data.ContextURL;
import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.http.HttpHeader;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.apache.olingo.server.api.*;
import org.apache.olingo.server.api.processor.EntityProcessor;
import org.apache.olingo.server.api.serializer.EntitySerializerOptions;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.api.serializer.SerializerResult;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.api.uri.UriParameter;
import org.apache.olingo.server.api.uri.UriResource;
import org.apache.olingo.server.api.uri.UriResourceEntitySet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.util.List;

/**
 *
 * 依据主键 Processor
 * @author chenYX
 * @date 2021/6/22 16:22
 * @description
 */
@Component
@Slf4j
public class SimpleEntityProcessor implements EntityProcessor {

    @Autowired
    private OdataJdbcUtils odataJdbcUtils;

    @Override
    public void readEntity(ODataRequest oDataRequest, ODataResponse oDataResponse, UriInfo uriInfo, ContentType contentType) throws ODataApplicationException, ODataLibraryException {
        // 1. retrieve the Entity Type
        List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
        UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) resourcePaths.get(0);
        EdmEntitySet edmEntitySet = uriResourceEntitySet.getEntitySet();

        // 2. retrieve the data from backend
        List<UriParameter> keyPredicates = uriResourceEntitySet.getKeyPredicates();

        String className = uriResourceEntitySet.getEntityType().getFullQualifiedName().getFullQualifiedNameAsString();
        Entity entity = new Entity();
        try {
            OdataClassMetaData odataClassMetaData = OdataCachedData.cachedCsdlMetaDataMap.get(className);
            Class aClass = odataClassMetaData.getAClass();
            OdataSqlInformation.SqlInformationBuild sqlInformationBuild = new OdataSqlInformation.SqlInformationBuild();
            sqlInformationBuild.createFilterString();
            sqlInformationBuild.buildPrimaryKeyAndClass(keyPredicates.get(0).getText(),aClass);
            OdataSqlInfo odataSqlInfo = sqlInformationBuild.buildSqlInfo();
            entity = odataJdbcUtils.executeSelectSqlAnd2Entity(odataSqlInfo);
        } catch (Exception e) {
            log.error("读取单个数据失败{}",e.getMessage(),e);
        }

        // 3. serialize
        EdmEntityType entityType = edmEntitySet.getEntityType();

        ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet).build();
        // expand and select currently not supported
        EntitySerializerOptions options = EntitySerializerOptions.with().contextURL(contextUrl).build();

        ODataSerializer serializer = odata.createSerializer(contentType);
        SerializerResult serializerResult = serializer.entity(serviceMetadata.get(), entityType, entity, options);
        InputStream entityStream = serializerResult.getContent();

        //4. configure the response object
        oDataResponse.setContent(entityStream);
        oDataResponse.setStatusCode(HttpStatusCode.OK.getStatusCode());
        oDataResponse.setHeader(HttpHeader.CONTENT_TYPE, contentType.toContentTypeString());
    }

    @Override
    public void createEntity(ODataRequest oDataRequest, ODataResponse oDataResponse, UriInfo uriInfo, ContentType contentType, ContentType contentType1) {

    }

    @Override
    public void updateEntity(ODataRequest oDataRequest, ODataResponse oDataResponse, UriInfo uriInfo, ContentType contentType, ContentType contentType1) throws ODataApplicationException, ODataLibraryException {

    }

    @Override
    public void deleteEntity(ODataRequest oDataRequest, ODataResponse oDataResponse, UriInfo uriInfo) throws ODataApplicationException, ODataLibraryException {

    }


    private OData odata;

    private ThreadLocal<ServiceMetadata> serviceMetadata = new ThreadLocal();

    @Override
    public void init(OData odata, ServiceMetadata serviceMetadata) {
        this.odata = odata;
        this.serviceMetadata.set(serviceMetadata);
    }
}
